#include "SchemaDB.h"

extern QSqlDatabase enjoylifedb;

using namespace std;

SchemaDB::SchemaDB()
{

}

/**
 * @brief SchemaDB::CreateSchemaDB
 * @return true sii la ejecución de query fue satisfactoria, es decir, se crearon
 * todas las tablas exitosamente.
 */
bool SchemaDB::CreateSchemaDB()
{
    enjoylifedb.setDatabaseName("enjoylifedb");

    QSqlQuery *query = new QSqlQuery(enjoylifedb);

    /**
      * Se elimina el tipo TEstadoCuenta en caso de que exista.
      */
    if (! query->exec("drop type if exists t_estado_cuenta cascade")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea el tipo TEstadoCuenta, que corresponde con el estado de la cuenta
      * del registro en nic.
      */
    if (! query->exec("create type t_estado_cuenta as enum ('Reservado','Registrado','Vencido','Congelado')")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se elimina el tipo TTipoTel en caso de que exista.
      */
    if (! query->exec("drop type if exists t_tipo_tel cascade")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea el tipo TTipoTel, que corresponde con el tipo de telefono.
      */
    if (! query->exec("create type t_tipo_tel as enum ('Fijo','Movil')")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "cliente" con la clausula "if not exists", es decir, si la
      * tabla no existe, la misma será creada, en caso contrario, no lo hará.
      */
    if (! query->exec("create table if not exists cliente "
                      "(nro_cliente serial, "
                      "razon_social varchar(60) unique not null, "
                      "responsable varchar(60) not null, "
                      "logo_cliente bytea, "
                      "fecha_alta date not null, "
                      "calle varchar(50) not null, "
                      "numero integer not null, "
                      "piso integer, "
                      "dpto varchar(30), "
                      "barrio varchar(30), "
                      "ciudad varchar(30) not null, "
                      "provincia varchar(30) not null, "
                      "tipo_tel_1 varchar(5), "
                      "telefono_1 varchar(20), "
                      "tipo_tel_2 varchar(5), "
                      "telefono_2 varchar(20), "
                      "email_1 varchar(60), "
                      "email_2 varchar(60), "
                      "cuit_cuil varchar(15), "
                      "estado varchar(5), "
                      "iva varchar(30), "
                      "constraint cliente_pkey primary key (nro_cliente))")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "cliente_eliminado" con la clausula "if not exists", es decir, si la
      * tabla no existe, la misma será creada, en caso contrario, no lo hará.
      */
    if (! query->exec("create table if not exists cliente_eliminado "
                      "(nro_cliente serial, "
                      "razon_social varchar(60) not null, "
                      "responsable varchar(60) not null, "
                      "fecha_baja date not null, "
                      "hora_baja time not null, "
                      "constraint cliente_eliminado_pkey primary key (nro_cliente))")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "dominio" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists dominio "
                      "(id_dominio serial, "
                      "d_razon_social varchar(60) not null, "
                      "val_dominio varchar(50) not null, "
                      "es_primaria varchar(11) not null, "
                      "fecha_alta_nic date not null, "
                      "fecha_vencimiento_nic date not null, "
                      "usuario_cpanel varchar(50), "
                      "contrasenia_cpanel varchar(30), "
                      "registrante_nic varchar(30), "
                      "email_registrante_nic varchar(50), "
                      "constraint pk_dominio primary key (id_dominio), "
                      "constraint fk_dominio_cliente foreign key(d_razon_social) references cliente(razon_social) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "autoadministrable" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists autoadministrable "
                      "(id_autoadmin serial, "
                      "a_razon_social varchar(60) not null, "
                      "seccion varchar(50) not null, "
                      "link varchar(150) not null, "
                      "usuario varchar(50) not null, "
                      "contrasenia varchar(50) not null, "
                      "constraint pk_autoadmin primary key (id_autoadmin), "
                      "constraint fk_autoadmin_cliente foreign key(a_razon_social) references cliente(razon_social) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se elimina el tipo TTipoMoneda en caso de que exista.
      */
    if (! query->exec("drop type if exists t_tipo_moneda cascade")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "persona" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists persona "
                      "(id_persona serial not null, "
                      "persona varchar(200) not null, "
                      "estado varchar(5), "
                      "constraint pk_persona primary key (persona))")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "concepto" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists concepto "
                      "(id_concepto serial not null, "
                      "concepto varchar(300) not null, "
                      "tipo_concepto varchar(8), "
                      "constraint pk_concepto primary key (concepto))")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "movimiento" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists movimiento "
                      "(id_mov serial not null, "
                      "fecha_mov date not null, "
                      "m_persona varchar(200), "
                      "m_concepto varchar(300), "
                      "tipo_moneda varchar(30), "
                      "idMoneda varchar(100),"
                      "debe float not null, "
                      "haber float not null, "
                      "idCtaCte varchar(500),"
                      "constraint pk_movimiento primary key (id_mov), "
                      "constraint fk_movimiento_persona foreign key(m_persona) references persona(persona) on delete cascade on update cascade) ")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }
    //    "constraint fk_movimiento_concepto foreign key(m_concepto) references concepto(concepto) on delete cascade on update cascade)"

//    if (! query->exec("alter table movimiento drop column idcheque")) {
//        ShowCriticalError(query->lastError().text());
//        return false;
//    }

//    if (! query->exec("alter table movimiento add column idCheque varchar(100)")) {
//        ShowCriticalError(query->lastError().text());
//        return false;
//    }

    /**
      * Se crea la tabla "cheque" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists cheque "
                      "(id_cheque serial not null, "
                      "nro_cheque varchar(100), "
                      "banco varchar(100), "
                      "fecha_recibido date not null, "
                      "fecha_cobro date not null, "
                      "c_persona varchar(200), "
                      "c_concepto varchar(300), "
                      "monto float not null, "
                      "cobrado varchar(3),"
                      "constraint pk_cheque primary key (id_cheque), "
                      "constraint fk_cheque_persona foreign key(c_persona) references persona(persona) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

//    "constraint fk_cheque_concepto foreign key(c_concepto) references concepto(concepto) on delete cascade on update cascade)"

//    if (! query->exec("alter table cheque add column cobrado varchar(3)")) {
//        ShowCriticalError(query->lastError().text());
//        return false;
//    }

    /**
      * Se crea la tabla "cuenta corriente" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists cuenta_corriente "
                      "(id_cuenta_cor serial not null, "
                      "cc_razon_social varchar(60) not null, "
                      "tipo_cobro varchar(50) not null, "
                      "concepto varchar(300), "
                      "debe float not null, "
                      "desde date not null, "
                      "estado_deuda varchar(60), "
                      "tipo_moneda varchar(30), "
                      "id_moneda varchar(100), "
                      "fecha_pago date, "
                      "recibo_generado varchar(2), "
                      "monto_pagado float, "
                      "descripción varchar(500), "
                      "constraint pk_cc primary key (id_cuenta_cor), "
                      "constraint fk_cc_cliente foreign key(cc_razon_social) references cliente(razon_social) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "cobro mensual" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists cobro_mensual "
                      "(id_cobro_mensual serial not null, "
                      "cm_razon_social varchar(60) not null, "
                      "concepto varchar(100) not null, "
                      "debe float not null, "
                      "desde date not null, "
                      "estado_deuda varchar(60), "
                      "tipo_cobro varchar(50) not null, "
                      "descripcion varchar(500), "
                      "id_cuenta_cor integer, "
                      "constraint pk_cobro primary key (id_cobro_mensual, cm_razon_social), "
                      "constraint fk_cobro_cliente foreign key(cm_razon_social) references cliente(razon_social) on delete cascade on update cascade, "
                      "constraint fk_id_cuenta_cor foreign key(id_cuenta_cor) references cuenta_corriente(id_cuenta_cor) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "pago mensual" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists pago_mensual "
                      "(id_pago_mensual serial not null, "
                      "pm_razon_social varchar(60) not null, "
                      "anio integer not null, "
                      "mes varchar(12), "
                      "monto varchar(12), "
                      "pago varchar(12), "
                      "constraint pk_pm primary key (id_pago_mensual, pm_razon_social), "
                      "constraint fk_pagom_cliente foreign key(pm_razon_social) references cliente(razon_social) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "deuda" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists deuda "
                      "(id_deuda serial not null, "
                      "d_razon_social varchar(60) not null, "
                      "concepto varchar(300) not null, "
                      "monto float not null, "
                      "total float not null, "
                      "constraint pk_deuda primary key (id_deuda, d_razon_social), "
                      "constraint fk_deuda_cliente foreign key(d_razon_social) references cliente(razon_social) on delete cascade on update cascade)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se elimina el tipo TTipoGasto en caso de que exista.
      */
    if (! query->exec("drop type if exists t_tipo_gasto cascade")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea el tipo TEstadoCuenta, que corresponde con el estado de la cuenta
      * del registro en nic.
      */
    if (! query->exec("create type t_tipo_gasto as enum ('Mensual','Esporádico')")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

    /**
      * Se crea la tabla "gasto por mes" con la clausula "if not exists", para evitar
      * crear siempre la tabla.
      */
    if (! query->exec("create table if not exists gasto_mes "
                      "(id_gasto_mes serial primary key, "
                      "fecha_gasto date not null, "
                      "concepto varchar(300) not null, "
                      "monto float not null, "
                      "estado_pago varchar(50) not null, "
                      "tipo_gasto varchar(50) not null, "
                      "observaciones varchar(200), "
                      "quien_pago varchar(30) not null)")) {
        ShowCriticalError(query->lastError().text());
        return false;
    }

//    /**
//    * Seccion para hacer modificaciones en la base de datos.
//    */
//    if (! query->exec("alter table cliente "
//                      "add column usuario_cpanel varchar(50) not null, "
//                      "add column contrasenia_cpanel varchar(30) not null, "
//                      "add column registrante_nic varchar(30) not null, "
//                      "add column email_registrante_nic varchar(50) not null, "
//                      "add column fecha_alta_nic date not null, "
//                      "add column fecha_vencimiento_nic date not null")) {
//        ShowCriticalError(query->lastError().text());
//        return false;
//    }

    return true;
}

/**
* Muestra el mensaje de error en caso de producirse uno de ellos. Toma como parametro
* un texto que es el detalle de la información del mensaje.
*/
void SchemaDB::ShowCriticalError(const QString &text)
{
    QMessageBox msg;
    msg.setStyleSheet("background-color: rgb(0, 139, 56);color: rgb(255, 255, 255);font: 12pt \"Helvetica57-Condensed\";border-style: solid");
    msg.setIcon(QMessageBox::Critical);
    msg.setText("Se ha producido un error. Por favor, intente nuevamente.");
    msg.setDetailedText(text);
    msg.addButton("Cerrar",QMessageBox::AcceptRole);
    msg.setWindowTitle("Alerta!");
    msg.exec();
}
